package com.beiming.libra.video.util;

import com.alibaba.fastjson.JSONObject;
import com.beiming.libra.video.config.LiveConfig;
import com.beiming.libra.video.domain.GetTestPushUrlRsp;
import com.beiming.libra.video.domain.StreamIDS;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Date;
import java.util.Map;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Component
@Slf4j
public class LiveUtil {

  @Resource
  RestTemplate restTemplate;

  /**
   * 从推流地址中提取流ID，完整的(推流状态检查) + 去掉bizid前缀的(生成对应的播放地址)
   */
  public StreamIDS getStreamIdFromPushUrl(String pushUrl) {
    int index = pushUrl.indexOf("?");
    if (index == -1) {
      return null;
    }
    String substr = pushUrl.substring(0, index);
    int indexResult = substr.lastIndexOf("/");
    String streamID = substr.substring(indexResult + 1, index);
    String prefix = LiveConfig.APP_BIZID + "_";
    String subID = streamID.substring(prefix.length(), streamID.length());
    StreamIDS ids = new StreamIDS();
    ids.setStreamID(streamID);
    ids.setSubID(subID);
    return ids;
  }


  /**
   * 生成混流地址
   */
  public String genMixedPlayUrl(String subID, String suffix) {
    String liveCode = LiveConfig.APP_BIZID + "_" + subID;
    return "https://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode + "."
        + suffix;
  }

  /**
   * 生成一组播放地址
   */
  public GetTestPushUrlRsp getTestPushUrl(String userID) {
    GetTestPushUrlRsp rsp = new GetTestPushUrlRsp();
    long txTime = System.currentTimeMillis() / 1000 + LiveConfig.VALID_TIME;
    String liveCode = LiveConfig.APP_BIZID + "_" + userID;
    String txSecret = Utils
        .getMD5(LiveConfig.PUSH_SECRET_KEY + liveCode + Long.toHexString(txTime).toUpperCase());
    String ext = "?APP_BIZID=" + LiveConfig.APP_BIZID + "&txSecret=" + txSecret + "&txTime=" + Long
        .toHexString(txTime).toUpperCase();
    String pushUrl =
        "rtmp://" + LiveConfig.APP_BIZID + ".livepush.myqcloud.com/live/" + liveCode + ext;
    String flvPlayUrl =
        "http://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode + ".flv";
    String rtmpPlayUrl =
        "rtmp://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode;
    String hlsPlayUrl =
        "http://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode + ".m3u8";
    String accPlayUrl =
        "rtmp://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode + ext;
    rsp.setUrlPush(pushUrl);
    rsp.setUrlPlayFlv(flvPlayUrl);
    rsp.setUrlPlayRtmp(rtmpPlayUrl);
    rsp.setUrlPlayHls(hlsPlayUrl);
    rsp.setUrlPlayAcc(accPlayUrl);
    return rsp;
  }

  /**
   * 向云直播后台请求混流操作
   */
  public String mergeStream(Map map) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    UriComponentsBuilder builder = UriComponentsBuilder
        .fromHttpUrl("http://fcgi.video.qcloud.com/common_access" + getQueryString());

    HttpEntity<String> entity = new HttpEntity<String>(
        JSONObject.toJSONString(map.get("mergeParams")), headers);

    ResponseEntity<String> response = restTemplate.exchange(
        builder.build().encode().toUri(),
        HttpMethod.POST,
        entity,
        String.class);

    log.info("mergeStream response: " + response.toString());

    return response.getBody();
  }

  private String getQueryString() {
    long txTime = System.currentTimeMillis() / 1000 + 60;
    String txSecret = Utils.getMD5(LiveConfig.APIKEY + txTime);
    String query = "?appid=" + LiveConfig.APP_ID
        + "&interface=mix_streamv2.start_mix_stream_advanced&t=" + txTime + "&sign=" + txSecret;
    return query;
  }


  /**
   * 生成加速拉流播放地址
   * 此处userId为userId_homeId(房间号)
   */
  public static String genAcceleratePlayUrl(String userId) {
    LiveConfig liveConfig = new LiveConfig();
    Long txTime = new Date().getTime() + LiveConfig.VALID_TIME;
    // liveCode即为streamId,需要推送给腾讯
    String liveCode = LiveConfig.APP_BIZID + '_' + userId;

    String time = null;
    try {
      time = Long.toHexString(txTime / 1000L).toUpperCase();
    } catch (NumberFormatException e) {
      e.printStackTrace();
    }
    String txSecret = md5(LiveConfig.PUSH_SECRET_KEY + liveCode + time);

    String ext =
        "?" + "bizid=" + LiveConfig.APP_BIZID + "&txSecret=" + txSecret + "&txTime=" + time;

    String playerUrl =
        "rtmp://" + LiveConfig.APP_BIZID + ".liveplay.myqcloud.com/live/" + liveCode + ext;
    return playerUrl;
  }

  /**
   * 生成推流地址
   */
  public static String genPushUrl(String userId) {
    LiveConfig liveConfig = new LiveConfig();
    Long txTime = new Date().getTime() + LiveConfig.VALID_TIME;
    String liveCode = LiveConfig.APP_BIZID + '_' + userId;

    String time = null;
    try {
      time = Long.toHexString(txTime / 1000L).toUpperCase();
    } catch (NumberFormatException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    String txSecret = md5(LiveConfig.PUSH_SECRET_KEY + liveCode + time);

    String ext =
        "?" + "bizid=" + LiveConfig.APP_BIZID + "&txSecret=" + txSecret + "&txTime=" + time;

    String playerUrl =
        "rtmp://" + LiveConfig.APP_BIZID + ".livepush.myqcloud.com/live/" + liveCode + ext;
    return playerUrl;
  }

  /**
   * md5
   */
  public static String md5(byte[] bytes) {
    String result = "";
    try {
      MessageDigest m = MessageDigest.getInstance("MD5");
      m.update(bytes);
      result = Hex.encodeHexString(m.digest());
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
   * md5
   */
  public static String md5(String str) {
    try {
      return md5(str.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return "";
  }
}
